/*
 * Copyright 2022 NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <stdio.h>
#include <string.h>

#include "fsl_debug_console.h"
#include "fsl_iomuxc.h"

#define WAV_MAX  1

extern uint8_t wav_data1[];
uint8_t* wav_data[WAV_MAX] = {wav_data1};
extern uint8_t wav_data1_end[];
extern uint32_t wav_file1_size;

typedef struct {
    char name[64];
    uint32_t raw_data_off;
    uint32_t raw_data_len;
}wav_info_t;

wav_info_t wav_files[WAV_MAX];

char *get_file_extension(const char *filename) {
    char *dot = strrchr(filename, '.');
    if (dot == NULL) {
        return "";
    }
    return dot + 1;
}

typedef struct {
    char riff[4]; // RIFF header
    uint32_t file_size; // File size in bytes
    char wave[4]; // WAVE header
    char fmt_chunk_marker[4]; // fmt sub-chunk marker
    uint32_t length_of_fmt; // Length of the fmt sub-chunk
    uint16_t audio_format; // Audio format (e.g. PCM, MP3)
    uint16_t num_channels; // Number of channels (e.g. mono, stereo)
    uint32_t sample_rate; // Sampling rate in Hz
    uint32_t byte_rate; // Byte rate in bytes per second
    uint16_t block_align; // Block align in bytes
    uint16_t bits_per_sample; // Bits per sample (e.g. 16-bit, 32-bit)
    char data_chunk_header[4]; // Data sub-chunk header
    uint32_t data_size; // Size of the data sub-chunk in bytes    
}wav_header_t;

uint32_t find_raw_data(uint8_t* file_data, uint32_t *data_len){
    wav_header_t header;
		uint8_t* data_search_ptr = file_data;
    memcpy((void*)&header, file_data, sizeof(header));
		data_search_ptr += sizeof(header);
    // data in header, standard wav
    if(!memcmp(header.data_chunk_header, "data", sizeof(header.data_chunk_header))){
        *data_len = header.data_size;
        goto quit;
    }
    // 'bext', bwf audio, loop to find the data
    while(1){
        uint8_t data[4];
//        f_read(f, data, 1, NULL);
				memcpy(data, data_search_ptr, 1);
				data_search_ptr += 1;
        if(data[0] == 'd'){
//            f_read(f, &data[1], 3, NULL);
						memcpy(&data[1], data_search_ptr, 3);
						data_search_ptr += 3;
            if(memcmp((const char*)data, "data", 4)){
                // not found, need to re-set the file-pointer
//                f_lseek(f, f_tell(f) - 3);
								data_search_ptr -= 3;
                continue;
            }else{
                // find the data, continue to find the data len
//                f_read(f, data, 4, NULL);
								memcpy(data, data_search_ptr, 4);
								data_search_ptr += 4;
                *data_len = *((uint32_t*)data);
                break;
            }
        }
    }
    quit:
    PRINTF("Data Len %d \r\n", *data_len);
    return data_search_ptr - file_data;   
}

int scan_wav(void)
{
		for(uint8_t i = 0; i < WAV_MAX; ++i){
				wav_files[i].raw_data_off = find_raw_data(wav_data[i], &(wav_files[0].raw_data_len));
		}
    return 0;
}

static uint8_t* cur_data_ptr = NULL;
static uint8_t * cur_wav = NULL;
static uint32_t audio_index;
int get_sound_data(void* data, uint32_t wanted_len){
	
    if(WAV_MAX == 0){
        // without any valid audio
        return -1;
    }

    wanted_len <<= 1;
    if(cur_data_ptr == NULL){
        // we need to open the first wav
				audio_index = 0;
        cur_wav = wav_data[audio_index];
				cur_data_ptr = cur_wav + wav_files[audio_index].raw_data_off;
//        open_and_seek(p_cur_f, &wav_files[audio_index]);
    }
    
    uint32_t get_len = 0;
    do{
        // get enough data	
				uint32_t remain_len = wav_files[audio_index].raw_data_len - (cur_data_ptr - cur_wav);
				if(remain_len >= wanted_len - get_len)	{
					memcpy(&data[get_len], cur_data_ptr, wanted_len);
					cur_data_ptr += wanted_len;
					break;
				}
				else{
					memcpy(&data[get_len], cur_data_ptr, remain_len);
					get_len += remain_len;
					audio_index = (audio_index + 1) % (WAV_MAX);
					cur_wav = wav_data[audio_index];
					cur_data_ptr = cur_wav + wav_files[audio_index].raw_data_off;
				}
    }while(1); 

    return 0;
}


